//////////////////////////////////////////////////////////////////////////
//
// Vector Graph Core2D
//
// Module:
//        Stretch2D.cs
//
// Description:
//        Implementation of stretch operation
//
// Author:
//        Created on 2008.04.18 by Destrayer
//
//////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace VectorGraph.Core2D
{
    class Stretch2D
    {
        public static void Stretch(ref Point2d pt, Rectangle2d range, Point2d v)
        {
            if (pt.X > range.Left && pt.X < range.Right && pt.Y > range.Bottom && pt.Y > range.Top)
            {
                pt += v;
            }
        }

        public static void Stretch(ref Rectangle2d rect, Rectangle2d range, Point2d v)
        {
            // if the rectangle intersect with the specified range, move it wholly
            if (Box2D.BoxIntBox(range, rect))
            {
                rect.LeftBottom += v;
                rect.RightTop += v;
            }
        }

        public static void Stretch(ref Segment2d seg, Rectangle2d range, Point2d v)
        {
            Stretch2D.Stretch(ref seg.StartPt, range, v);
            Stretch2D.Stretch(ref seg.EndPt, range, v);
        }

        public static void Stretch(ref Arc2d arc, Rectangle2d range, Point2d v)
        {
            Point2d pt1 = arc.StartVector + arc.CenterPt;
            Point2d pt2 = arc.EndVector + arc.CenterPt;
            bool b1 = pt1.X > range.Left && pt1.X < range.Right && pt1.Y > range.Bottom && pt1.Y > range.Top;
            bool b2 = pt2.X > range.Left && pt2.X < range.Right && pt2.Y > range.Bottom && pt2.Y > range.Top;
            if (b1 && b2)
            {
                arc.CenterPt += v;
                return;
            }
            if (!b1 && !b2)
            {
                return;
            }
            if (b1)
            {
                pt1 += v;
            }
            else if (b2)
            {
                pt2 += v;
            }

            double radius2 = arc.StartVector.SqrLength;
            double halfChord2 = pt1.SqrDistance(pt2) / 4;
            if (halfChord2 > radius2)
            {
                arc.CenterPt += v;
            }
            else
            {
                Point2d midPt = pt2 + pt1;
                midPt.Scale(0.5);
                Point2d c = pt1 - midPt;
                c.Scale(Math.Sqrt(radius2 / halfChord2 - 1));
                c += midPt;
                Point2d c1 = c;
                c1.X = -c.Y;
                c1.Y = c.X;
                Point2d c2 = c1;
                c2.Inverse();
                // if may fail when the two new positions get the same distance to the original arc center
                if (c2.SqrDistance(arc.CenterPt) < c1.SqrDistance(arc.CenterPt))
                {
                    c1 = c2;
                }
                arc.CenterPt = c1;
                arc.StartVector = pt1 - c1;
                arc.EndVector = pt2 - c1;
            }
        }
    }
}
